package com.example.android.BluetoothChat;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder.AudioSource;
import android.os.Environment;
import android.util.Log;

/**
 * 
 * @author zyfgeliang
 * 
 */
public class PCMAudioRecoder {
	/**
	 * ��Ƶ�ɼ�������ӿ�
	 * 
	 * @author zyfgeliang
	 * 
	 */
	public interface recordeOutputCallBack {
		/**
		 * 
		 * @param data
		 *            pcm raw
		 * @param size
		 *            pcm size
		 */
		void recordeOutput(byte[] data, int size);
	}

	final static String TAG = PCMAudioRecoder.class.getSimpleName();
	private recordeOutputCallBack mRecordeOutputCallBack = null;
	private int audioSource = AudioSource.MIC;
	private int audioStreamType = AudioManager.STREAM_VOICE_CALL;
	private int bufferSizeInBytes;
	private AudioRecord audioRecord;
	private boolean isRecording;
	// ������Ƶ�����ʣ�44100��Ŀǰ�ı�׼������ĳЩ�豸��Ȼ֧��22050��16000��11025
	private static int sampleRateInHz = 8000;
	// ������Ƶ��¼�Ƶ����CHANNEL_IN_STEREOΪ˫�����CHANNEL_CONFIGURATION_MONOΪ�����
	private static int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
	// ��Ƶ��ݸ�ʽ:PCM 16λÿ������֤�豸֧�֡�PCM 8λÿ������һ���ܵõ��豸֧�֡�
	private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

	/**
	 * ¼�Ʋ�ͨ��ص������������
	 */
	public void recoder() {

		try {
			Log.e(TAG, "Recording is start");
			// Create a DataOuputStream to write the audio data into the
			// saved file.
			// Create a new AudioRecord object to record the audio.
			// ���������������С�������С
			bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
					channelConfig, audioFormat);
			// ����AudioRecord����
			audioRecord = new AudioRecord(audioSource, sampleRateInHz,
					channelConfig, audioFormat, bufferSizeInBytes);
			byte[] buffer = new byte[bufferSizeInBytes];
			audioRecord.startRecording();
			isRecording = true;
			while (isRecording) {
				int bytesRecord = audioRecord
						.read(buffer, 0, bufferSizeInBytes);
				if (bytesRecord == AudioRecord.ERROR_INVALID_OPERATION) {
					Log.e(TAG,
							"AudioRecord.read() returned AudioRecord.ERROR_INVALID_OPERATION");
				} else if (bytesRecord == AudioRecord.ERROR_BAD_VALUE) {
					Log.e(TAG,
							"AudioRecord.read() returned AudioRecord.ERROR_BAD_VALUE");
				} else if (bytesRecord == AudioRecord.ERROR) {
					Log.e(TAG, "AudioRecord.read() returned AudioRecord.ERROR");
				} else {
					if (mRecordeOutputCallBack != null) {
						// Thread.sleep(30);
						Log.i(TAG,
								"read  size:"
										+ String.format("%d", bytesRecord));
						if (bytesRecord > 0) {
							mRecordeOutputCallBack.recordeOutput(buffer,
									bytesRecord);
						}
					}
				}
			}
			audioRecord.stop();
			audioRecord.release();// �ͷ���Դ
			audioRecord = null;
			Log.i(TAG, "Recording is stop");
		} catch (Exception t) {
			t.printStackTrace();
			Log.e(TAG, "Recording Failed");
		}
	}

	/**
	 * ¼�Ƶ��ļ�
	 */
	public void recoderToFile() {
		File file = new File(Environment.getExternalStorageDirectory()
				.getAbsolutePath() + "/temp.pcm");
		// ɾ��¼���ļ�
		if (file.exists())
			file.delete();
		// ����¼���ļ�
		try {
			file.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
		try {
			Log.e("AudioRecord", "Recording is start");
			// Create a DataOuputStream to write the audio data into the
			// saved file.
			FileOutputStream fos = new FileOutputStream(file);// ����һ���ɴ�ȡ�ֽڵ��ļ�
			// Create a new AudioRecord object to record the audio.
			// ���������������С�������С
			bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
					channelConfig, audioFormat);
			// ����AudioRecord����
			audioRecord = new AudioRecord(audioSource, sampleRateInHz,
					channelConfig, audioFormat, bufferSizeInBytes);
			byte[] buffer = new byte[bufferSizeInBytes];
			audioRecord.startRecording();
			isRecording = true;
			while (isRecording) {
				audioRecord.read(buffer, 0, bufferSizeInBytes);
				fos.write(buffer);
				if (mRecordeOutputCallBack != null) {
					Log.i("AudioRecord", "Recording is output");
					mRecordeOutputCallBack.recordeOutput(buffer,
							bufferSizeInBytes);
				}
			}
			audioRecord.stop();
			audioRecord.release();// �ͷ���Դ
			audioRecord = null;
			fos.flush();
			fos.close();
			Log.e("AudioRecord", "Recording is stop");
		} catch (Exception t) {
			t.printStackTrace();
			Log.e("AudioRecord", "Recording Failed");
		}
	}

	/**
	 * ���ⲿ�Խ�����ӿ�
	 * 
	 * @param mRecordeOutputCallBack
	 */
	public void setRecordeOutputCallBack(
			recordeOutputCallBack mRecordeOutputCallBack) {
		this.mRecordeOutputCallBack = mRecordeOutputCallBack;
	}

	public void backPlay() {
		// �������ļ�
		File file = new File(Environment.getExternalStorageDirectory()
				.getAbsolutePath() + "/temp.pcm");
		FileInputStream in = null;
		try {
			in = new FileInputStream(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return;
		}
		// ���������������С�������С
		bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
				channelConfig, audioFormat);
		byte[] buffer = new byte[bufferSizeInBytes];
		int byteread = 0;
		AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
				sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes,
				AudioTrack.MODE_STREAM);
		// ����
		audioTrack.play();
		try {
			while ((byteread = in.read(buffer)) != -1) {
				System.out.write(buffer, 0, byteread);
				System.out.flush();
				Log.i("AudioTrack output length", String.format("%d", byteread));
				audioTrack.write(buffer, 0, byteread);
			}
			in.close();
			audioTrack.stop();
			audioTrack.release();
		} catch (Exception e) {
			e.printStackTrace();
			Log.e("AudioTrack", "Playback Failed");
		}
	}

	public void stopRecode() {
		isRecording = false;
	}

	AudioTrack audioTrack;

	public void backPlay(byte[] buffer, int size) {
		if (audioTrack == null) {
			audioTrack = initPlayer();
		}
		try {

			int bytesRecord = audioTrack.write(buffer, 0, size);
			if (bytesRecord == AudioRecord.ERROR_INVALID_OPERATION) {
				Log.e(TAG,
						"AudioRecord.read() returned AudioRecord.ERROR_INVALID_OPERATION");
			} else if (bytesRecord == AudioRecord.ERROR_BAD_VALUE) {
				Log.e(TAG,
						"AudioRecord.read() returned AudioRecord.ERROR_BAD_VALUE");
			} else if (bytesRecord == AudioRecord.ERROR_INVALID_OPERATION) {
				Log.e(TAG,
						"AudioRecord.read() returned AudioRecord.ERROR_INVALID_OPERATION");
			} else {
				Log.e(TAG, "AudioTrack.PlaybackING .. " + size);
			}
		} catch (Exception e) {
			e.printStackTrace();
			Log.e("AudioTrack", "Playback Failed");
		}
	}

	public void stopPlayer() {
		if (audioTrack != null) {
			audioTrack.stop();
			audioTrack.release();
		}

	}

	private AudioTrack initPlayer() {
		bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
				channelConfig, audioFormat);
		AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
				sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes,
				AudioTrack.MODE_STREAM);
		audioTrack.play();
		return audioTrack;
	}
}
